﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace Stopwatch {
    public partial class StopWatchCtl : UserControl {

        private System.Diagnostics.Stopwatch swRun;
        private System.Diagnostics.Stopwatch swPause;
        private bool _running;
        private bool _paused;

        private Laptime _lastLapTime;
 
        public StopWatchCtl() {
            InitializeComponent();
            this.swRun = new System.Diagnostics.Stopwatch();
            this.swPause = new System.Diagnostics.Stopwatch();
        }

        private void btnStop_Click(object sender, EventArgs e) {
            if (this._running) {
                this.StopStopwatch();
            } else {
                this.StartStopwatch();
            }
        }

        public void StartStopwatch() {
            this.swRun = new System.Diagnostics.Stopwatch();
            this.swPause = new System.Diagnostics.Stopwatch();
            this.swRun.Start();

            this._running = true;
            this._paused = false;

            this.lblStartTime.Text =
                DateTime.Now.ToLongTimeString();

            this._lastLapTime = null;

            this.btnStop.BackColor = Color.LightCoral;
            this.btnStop.Text = "Stop";

            this.btnLap.Enabled = true;
            this.btnPause.Enabled = true;

            this.CleanLapTimes();
            this.OnStateChanged(EventArgs.Empty);
            this.FastScreenUpdate();
        }

        public void StopStopwatch() {
            this.swRun.Stop();
            this.swPause.Stop();

            this._running = false;
            this._paused = false;

            this.btnStop.BackColor = Color.LightGreen;
            this.btnStop.Text = "Start";

            this.btnLap.Enabled = false;
            this.btnPause.Enabled = false;

            this.timer1_Tick(this, EventArgs.Empty);
            this.SlowScreenUpdate();
            this.OnStateChanged(EventArgs.Empty);
        }

        private void CleanLapTimes() {
            this.listView1.Items.Clear();
            this._lastLapTime = null;
        }

        private void timer1_Tick(object sender, EventArgs e) {
            if (this.IsDisposed) {
                return;
            }
            if (this.swRun == null || this.swPause == null) {
                return;
            }
            this.lblTimer.Text = this.FormatTimespan(this.swRun.Elapsed);
            this.lblPauseTime.Text = this.FormatTimespan(this.swPause.Elapsed);
        }

        private string FormatTimespan(TimeSpan ts) {
            if (ts.Days > 0) {
                return string.Format(
                    "{0} {1:00}:{2:00}:{3:00}.{4:00}",
                    ts.Days,
                    ts.Hours,
                    ts.Minutes,
                    ts.Seconds,
                    ts.Milliseconds / 10);
            } else {
                return string.Format(
                    "{1:00}:{2:00}:{3:00}.{4:00}",
                    ts.Days,
                    ts.Hours,
                    ts.Minutes,
                    ts.Seconds,
                    ts.Milliseconds / 10);
            }
        }

        private void btnPause_Click(object sender, EventArgs e) {
            if (!this._paused) {
                this.swPause.Start();
                this.swRun.Stop();
            } else {
                this.swPause.Stop();
                this.swRun.Start();
            }
            this._paused = !this._paused;
            this.timer1_Tick(this, EventArgs.Empty);
        }

        protected override void OnResize(EventArgs e) {
            base.OnResize(e);

            int width = this.ClientSize.Width;

            this.ScaleControls(this.lblStarted, this.lblPause, width);
            this.ScaleControls(this.lblStartTime, this.lblPauseTime, width);
            this.ScaleControls(this.btnStop, this.btnPause, this.btnLap, width);

            int colWidth = (width- columnIndex.Width) / 2 - 8;
            Debug.WriteLine(colWidth);
            this.columnLap.Width = colWidth;
            this.columnTotal.Width = colWidth;
        }

        private Pen _p;
        protected override void OnPaintBackground(PaintEventArgs e) {
            base.OnPaintBackground(e);
            if (_p == null) {
                _p = new Pen(Color.DarkGray);
            }
            e.Graphics.DrawLine(
                _p, 0, this.ClientSize.Height - 1,
                this.ClientSize.Width, this.ClientSize.Height - 1);
        }

        private void ScaleControls(Control left, Control right, int width) {
            var w = (width / 2) - 3;
            left.Width = w;
            right.Left = left.Right + 3;
            right.Width = w;
        }

        private void ScaleControls(Control left, Control center, Control right, int width) {
            var w = (width / 3) - 4;

            if (left != null) {
                left.Left = 3;
                left.Width = w;
            }
            if (center != null) {
                center.Left = (w + 6);
                center.Width = w;
            }
            if (right != null) {
                right.Left = (w * 2) + 9;
                right.Width = w;
            }
        }

        private void StopWatchCtl_Click(object sender, EventArgs e) {

        }

        private void btnLap_Click(object sender, EventArgs e) {
            this.Laptime();
        }

        public void Laptime() {
            var l = new Laptime(this.swRun.Elapsed, this._lastLapTime);
            this._lastLapTime = l;

            var lvi = new ListViewItem(new string[] {
                l.Nr.ToString(),
                FormatTimespan(l.Lap),
                FormatTimespan(l.Total) });

            this.listView1.Items.Add(lvi);
            this.OnStateChanged(EventArgs.Empty);
        }

        public bool Running {
            get {
                return this._running;
            }
        }

        public event EventHandler StateChanged;
        public void OnStateChanged(EventArgs e) {
            if (this.StateChanged != null) {
                this.StateChanged(this, e);
            }
        }

        public void FastScreenUpdate() {
            this.timer1.Interval = 50;
        }

        public void SlowScreenUpdate() {
            this.timer1.Interval = 5000;
        }
    }
}
